#include "Unit.h"

#include "renderer/GameRenderer.h"

#include <glm/gtc/matrix_transform.hpp>

namespace VectorTD
{
	Unit::Unit(GameRenderer::GameMesh* p_mesh, float p_baseSpeed, unsigned int p_baseHp, float p_rotationSpeed, float p_scale, Map* p_map)
		: m_mesh(p_mesh)
		, m_modelMat(glm::mat4(1.0f))
		, m_transMat(glm::mat4(1.0f))
		, m_rotMat(glm::mat4(1.0f))
		, m_scaleMat(glm::mat4(1.0f))
		, m_baseHp(p_baseHp)
		, m_baseSpeed(p_baseSpeed)
		, m_rotationSpeed(p_rotationSpeed)
		, m_map(p_map)
		, m_nextPathCell(0)
		, m_unitColor(0.0f, 1.0f, 1.0f, 1.0f)
	{
		ASSERT(p_scale < 1.0f && p_scale > 0.0f, "Invalide scale value for the unit: %f", p_scale);
		m_scaleMat = glm::scale(m_scaleMat, glm::vec3(p_scale, p_scale, 1.0f));
		m_transMat = glm::translate(m_transMat, glm::vec3(-0.5f * p_scale, -0.5f * p_scale, 0.0f));
	}

	bool Unit::Update(double p_deltaMs)
	{
		m_rotMat = glm::rotate(m_rotMat, static_cast<float>(m_rotationSpeed*p_deltaMs/1000.0f), glm::vec3(0.0f, 0.0f, 1.0f));

		if(m_nextPathCell < m_map->m_path.size())
		{
			glm::vec2 destination = glm::vec2((m_map->m_path[m_nextPathCell]->x + 0.5f)* m_map->GetSizeCell(), (m_map->m_path[m_nextPathCell]->y +0.5f) * m_map->GetSizeCell());
			glm::vec2 position = Position();

			glm::vec2 direction = destination - position;
			float t = direction.x * direction.x + direction.y * direction.y;
			if(t < 0.05f)
			{
				m_nextPathCell++;
				return true;
			}

			direction = glm::normalize(direction);

			direction *= 0.01f;

			m_transMat = glm::translate(m_transMat, glm::vec3(direction, 0.0f));
			m_modelMat = m_transMat * m_rotMat * m_scaleMat;
			return true;
		}
		else
			return false;
	}

	void Unit::Spawn(glm::vec2 p_startPosition)
	{
		m_transMat = glm::translate(m_transMat, glm::vec3(p_startPosition, 0.0f));
		
		m_modelMat = m_transMat * m_rotMat * m_scaleMat;
		GameRenderer& gr = GameRenderer::GetInstance();
		GameRenderer::ShaderParams sp;
		sp.model = &m_modelMat;
		sp.meshColor = &m_unitColor;
		gr.AddMeshToRender(m_mesh, sp);
		InsertUpdatable(this);
	}
	glm::vec2 Unit::Position()
	{
		return glm::vec2(m_transMat[3][0] + 0.5f * m_scaleMat[0][0], m_transMat[3][1] + 0.5f * m_scaleMat[0][0]);
	}

}